package com.spi.soconversion;

import java.io.File;
import java.sql.Timestamp;

import com.spi.soconversion.base.SOCException;
import com.spi.soconversion.base.data.OpenSalesOrderDataCollector;
import com.spi.soconversion.base.data.OpenSalesOrderDataProcessor;
import com.spi.soconversion.dao.BatchDAO;
import com.spi.soconversion.dao.BatchDAOImpl;
import com.spi.soconversion.dao.ConversionDAO;
import com.spi.soconversion.dao.ConversionDAOImpl;
import com.spi.soconversion.jmsqueue.JMSInitializer;
import com.spi.soconversion.util.ConversionType;
import com.spi.soconversion.util.ErrorConstants;
import com.spi.soconversion.util.ErrorMessageReader;
import com.spi.soconversion.util.ResourceProvider;
import com.spi.soconversion.util.SOCConstants;
import com.spi.soconversion.util.SOCFileWriter;
import com.spi.soconversion.util.SOCUtility;
import com.spi.soconversion.util.XMLValidator;

/**
 * A Controller class for Open Sales Order Module
 * 
 * @author XSPID41
 *
 */

public class OpenSalesOrderController implements IController {
		
	private SOCFileWriter d_FileWriter;
	private String d_logFileName;
	private long d_totalGoodRecords;

	private ResourceProvider provider;	
	private Batch batch;
	
	private BatchDAO batchDAO = new BatchDAOImpl();
	private ConversionDAO conversionDAO = new ConversionDAOImpl();
	private OpenSalesOrderDataProcessor osoDataProcessor = null;
	
    static private org.apache.commons.logging.Log log = 
        org.apache.commons.logging.LogFactory.getLog(OpenSalesOrderController.class);
	
    /**
     * Initialize the resources
     */
	public void init(String args) throws SOCException {
		log.info("Initializing the data for Open Sales Order...");		
		// load resources
		provider = ResourceProvider.getInstance();
		d_FileWriter = new SOCFileWriter();		
		d_logFileName = provider.getLogFileDirectory() + 
							SOCConstants.DELIMITER + SOCConstants.OPEN_SALES_ORDER_LOG_FILE + 
							SOCConstants.UNDERSCORE + SOCUtility.dateSuffix() + 
							SOCConstants.LOG_FILE_EXTN;
		
		// instantiate batch and set properties
		batch = new Batch();
		batch.setFileWriter(d_FileWriter);
		batch.setLogFileName(d_logFileName);
	}

	/**
	 * Fetch data from ORACLE order management tables based on the flag 
	 */
	public void fetch() throws SOCException {
		log.info("Fetching the data for Open Sales Order...");
    	if("Y".equals(provider.getFetchOpenSalesOrder())) {
    		OpenSalesOrderDataCollector oso = new OpenSalesOrderDataCollector();
    		oso.fetchData();
    	}
	}
	
	/**
	 * Convert the COFI Order Lines to MCF Orders
	 */
	public void process() throws SOCException {
		log.info("Processing the fetched data for Open Sales Order...");
		int d_batchNum = 0;
		
		if("N".equals(provider.getFetchOpenSalesOrder())) {
			Timestamp startTime = new Timestamp(System.currentTimeMillis());
			batch.setStartTime(startTime);
						
			int d_lastBatch = batchDAO.getBatchNumber(ConversionType.OPEN_SALES_ORDER.getDisplayText());
			int totalRecProcessed = 0;
			int totalRecToBeProcessed = 0;
			if(d_lastBatch > 0) {
				totalRecProcessed = batchDAO.getTotalRecordsProcessed(
						d_lastBatch,ConversionType.OPEN_SALES_ORDER.getDisplayText());
				totalRecToBeProcessed = batchDAO.getTotalRecordsToBeProcessed();
			}
			batch.setTotalRecProcessed(totalRecProcessed);
			batch.setToBeProcessedSize(totalRecToBeProcessed);
			
			d_batchNum= d_lastBatch+1; 
			batch.setBatchNumber(d_batchNum);
			
			String d_xmlOutputDirectory = ResourceProvider.getInstance().getXmlOutputDirectory() + 
											SOCConstants.DELIMITER + 
											SOCConstants.BATCH +
											SOCConstants.UNDERSCORE + 
											SOCConstants.OPEN_ORDER +
											SOCConstants.UNDERSCORE + 
											d_batchNum;
			batch.setXmlOutputDirectory(d_xmlOutputDirectory);
			
			//renaming log file
			File logFile = new File(d_logFileName);
			String timeStamp = d_logFileName.substring(d_logFileName.indexOf(SOCConstants.UNDERSCORE), d_logFileName.length());
			String log= SOCConstants.OPEN_SALES_ORDER_LOG_FILE+SOCConstants.UNDERSCORE+SOCConstants.BATCH+d_batchNum+timeStamp;
			boolean renameLogFile = false;
			d_FileWriter.closeFile(d_logFileName);		
			renameLogFile=logFile.renameTo(new File(provider.getLogFileDirectory(), log));
			
			String d_statisticsFile = ResourceProvider.getInstance().getLogFileDirectory() + 
										SOCConstants.DELIMITER +
										SOCConstants.EXECUTION_SUMMARY_FILE +
										SOCConstants.OPEN_SALES_ORDER_LOG_FILE + 
										SOCConstants.UNDERSCORE+SOCConstants.BATCH + 
										d_batchNum +
										timeStamp;
			provider.setStatisticsFile(d_statisticsFile);
			
//			if(!renameLogFile) {
//				d_FileWriter.write(d_logFileName, SOCUtility.writeLogMessage(SOCErrorMessageReader.getError(
//						SOCErrorConstants.FAILED_RENAME_LOG_FILE)+log));
//				throw new SOCException(
//						SOCErrorMessageReader.getError(
//								SOCErrorConstants.FAILED_RENAME_LOG_FILE)+log);
//			}
//			else {
//				d_logFileName=d_logFileDirectory+SOCConstants.DELIMITER+log;
//			}
			
			File xmlDirRef= new File(d_xmlOutputDirectory);
			if (xmlDirRef.exists()) {
				d_FileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
						ErrorConstants.BATCH_ALREADY_RUN)+d_batchNum));
				throw new SOCException(
						ErrorMessageReader.getError(
								ErrorConstants.BATCH_ALREADY_RUN)+d_batchNum);
			}
			else {
				xmlDirRef.mkdir();
			}
			
			int d_batchSize = provider.getBatchSize();
			batch.setBatchSize(d_batchSize);
						
			// instantiate data processor
			osoDataProcessor = new OpenSalesOrderDataProcessor(d_logFileName, d_FileWriter, batch);
			batch.setTotalRecordsProcessed(osoDataProcessor.processRecords());
			int recordsFetched = osoDataProcessor.getRecordsFetched();
			batch.setFetchSize(recordsFetched);

			Timestamp endTime = new Timestamp(System.currentTimeMillis());
			batch.setEndTime(endTime);
			
			int recordsProcessed = 0;
			if(d_batchSize > 0) {
				recordsProcessed = d_batchSize;
			}
			else {
				recordsProcessed = recordsFetched;
			}
			int ordersNotConverted = osoDataProcessor.getOrdersNotConverted();
			int recordsDataIssues= recordsProcessed -(osoDataProcessor.getCountXMLCreated() + ordersNotConverted);
			long recordsFailedValidation = osoDataProcessor.getCountXMLCreated()- d_totalGoodRecords;
			
			batch.setNotConvertedRecordsSize(ordersNotConverted);
			batch.setDataIssuesSize(recordsDataIssues);
			batch.setProcessedSize(recordsProcessed);
			batch.setRecordsFailedValidation(recordsFailedValidation);															
		}		
	}
					
	/**
	 * Validate the Converted Data
	 * @TODO
	 */
	public void validate() throws SOCException {
		log.info("Validating the data for Open Sales Order...");
		validateXML(); // no XSD validation required
	}

	/**
	 * Validates the XML file with the XSD file
	 * 
	 * @throws SOCException
	 */
	private void validateXML() throws SOCException {
		String xsdPath = provider.getXsdDirectory() + 
							SOCConstants.DELIMITER + SOCConstants.OPENSALES_XSD;
		XMLValidator validator= new XMLValidator(d_logFileName,d_FileWriter, 
							xsdPath,SOCConstants.OPEN_SALES_ORDER_XML_FILE, batch.getBatchNumber());
		d_totalGoodRecords=validator.validateXML(provider.getXmlOutputDirectory() );		
	}  

	/**
	 * Writes the statistics file and pushing the converted xml files into JMS Queue
	 */
	public void write() throws SOCException {
		log.info("Writing the data for Open Sales Order...");						
		log.info("-->Writing the batch statistics...");
		// write the statistics to a file
		writeBatchStatistics(batch);
		
		log.info("-->Pushing the XML files into the JMS Queue...");
		// Push the generated XML files to the JMS Queue
		String d_conversionType = ConversionType.OPEN_SALES_ORDER.getDisplayText();
		JMSInitializer jmsInitializer = 
			new JMSInitializer(batch.getXmlOutputDirectory(), batch.getBatchNumber(), d_logFileName, 
								d_FileWriter, d_conversionType);
		jmsInitializer.getDirectoriesForJMSQueue();
		jmsInitializer.sendFileToJMSQueue();
	}

	/**
	 * Writes the statistics to the file
	 * 
	 * @param recordsProcessed
	 * @param xmlCount
	 * @param recordsDataIssues
	 * @param recordsNotConverted
	 * @throws SOCException
	 */
	private void writeBatchStatistics(Batch batch) throws SOCException {
		log.info("-->Writing the statistics to the file...");
		String d_statisticsFile = provider.getStatisticsFile();
		d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_BATCH_NUMBER +
							batch.getBatchNumber()+SOCConstants.NEW_LINE);    	
		d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_TOTAL_ORDERS_CONVERTED +
							batch.getToBeProcessedSize()+SOCConstants.NEW_LINE);
		d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_TOTAL_ORDERS_PROCESSED_TILL_BATCH +
							batch.getTotalRecordsProcessed()+SOCConstants.NEW_LINE);
		d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_TOTAL_ORDERS_PROCESSED_BATCH +
							batch.getProcessedSize()+SOCConstants.NEW_LINE);
		d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_TOTAL_ORDERS_DATA_ISSUES_BATCH +
							batch.getDataIssuesSize()+SOCConstants.NEW_LINE);	
		d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_TOTAL_ORDERS_NOT_CONVERTED_BATCH +
							batch.getNotConvertedRecordsSize()+SOCConstants.NEW_LINE);
		if (batch.getXmlList() != null) {
			d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_TOTAL_ORDERS_CONVERTED_TO_XMLS_SUCCESSFULLY +
							batch.getXmlList().size()+SOCConstants.NEW_LINE);
		}
		d_FileWriter.write(d_statisticsFile,SOCConstants.MESSAGE_TOTAL_ORDERS_XMLS_PASSED_VALIDATION +
							d_totalGoodRecords+SOCConstants.NEW_LINE);
		d_FileWriter.closeFile(d_statisticsFile);
	}

	/**
	 * Update the batch and converted data information to database tables
	 */
	public void update() throws SOCException {
		log.info("Updating the data for Open Sales Order...");
		// update the batch Information
		batchDAO.updateBatch(batch);
		
		// update converted order information
		conversionDAO.updateConvertedOrdersInfo(osoDataProcessor.getConvertedOrderList(),
												osoDataProcessor.getNotConvertedOrderList(), batch);
		
		// release the resources
		log.info("-->Releasing the resources...");
		provider.closeDBConnection();			
		d_FileWriter.closeFile(d_logFileName);
	}	
}